use std::{
    collections::HashMap,
    fs,
    io::{self, BufRead},
};

/// 读取映射表.
/// 兼容一对多.
pub fn read_map(file_path: &str) -> HashMap<String, Vec<String>> {
    let file = fs::File::open(file_path).unwrap();
    let reader = io::BufReader::new(file);

    let mut result = HashMap::new();
    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<&str> = line.split_whitespace().collect();

        if parts.len() < 2 {
            continue;
        }

        let mut parts = parts.into_iter().map(|s| s.to_string());
        let key = parts.next().unwrap();
        let values = parts.collect();
        result.insert(key, values);
    }

    result
}

/// 词翻译器.
///
/// 词直接翻译失败就会逐字翻译.
pub struct WordTranslator {
    word_map: HashMap<String, Vec<String>>,
    ch_map: HashMap<String, Vec<String>>,
}

impl WordTranslator {
    /// 从一对多的表构建翻译器.
    pub fn with_map(
        word_map: HashMap<String, Vec<String>>,
        ch_map: HashMap<String, Vec<String>>,
    ) -> Self {
        Self { word_map, ch_map }
    }

    pub fn with_map_file_paths(word_path: &str, ch_path: &str) -> Self {
        let word_map = read_map(word_path);
        let ch_map = read_map(ch_path);
        Self::with_map(word_map, ch_map)
    }

    /// 词对词翻译.
    ///
    /// 无论何时遇到一对多时, 总是取第一个.
    pub fn trans(&self, input: &str) -> String {
        self.word_map
            .get(input)
            .map_or_else(|| self.trans_by_char(input), |s| s[0].clone())
    }

    fn trans_by_char(&self, input: &str) -> String {
        println!("DEBUG: trans_by_char: {input}");
        input.chars().map(|ch| self.trans_char(ch)).collect()
    }

    /// 翻译单个字符.
    ///
    /// 找不到就输出原char.
    fn trans_char(&self, ch: char) -> String {
        self.ch_map
            .get(&ch.to_string())
            .map(|s| s[0].clone())
            .unwrap_or(ch.to_string())
    }
}
